$(document).ready(function () {

    // 测试场景控件可拖拽
    SortableSceneGroup();
    // 案例/工具组件与逻辑组件可嵌套拖拽
    SortableNestedElement();

    // 渲染项目案例节点树
    renderElementCopyTree();

    // 支持页面左右分割
    renderSplitter();

    // 使用tippy.js插件为控件增加弹出提示框
    tippyBtnScene();
    tippyBtnAddScene();
    tippyBtnLogicController();
    tippyBtnAddCase();
    tippySceneName();
    tippyBtnCase();
    tippyCaseName();
    tippyLogicControllerContent();
    tippyBtnTool();
    tippyToolName();

    // 绑定事件
    $(document).on('keydown', documentSaveElement);
    $select_module.on('change', jumpToModule);
    $btn_start_module_test.on('click', startModuleTest);
    $btn_stop_module_test.on('click', stopModuleTest);
    $btn_mark.on('click', mark);
    $btn_clear_mark.on('click', clearMark);
    $button_add_scene.on('click', addScene);
    $div_case_names.on('mouseover', tippyCaseName);
    $div_scene_names.on('mouseover', tippySceneName);
    $div_tool_names.on('mouseover', tippyToolName);
    $div_logic_controller_contents.on('mouseover', tippyLogicControllerContent);
    $item_scene_group.on('click', '.item-case', clickItemCase);
    $item_scene_group.on('click', '.specific-logic-controller', clickLogicController);
    $item_scene_group.on('click', '.item-tool', clickTool);
    $select_project.on('change', selectProjectToCopy);
    $btn_element_copy.on('click', copyElementFromProjectTree);

    // iframe默认打开空白页面
    $iframe_case.attr('src','/blank');

    // 查询模块调度信息
    getModuleDispatcherInfo();
    // 遍历所有组件并初始化Dom
    traverseAllElementAndLoadDom();

});

let dispatcher_id = null; // 模块调度id 打开场景页面时查询返回调度id，或在调度启动主推拿到调度id
let sortable_nested_instance_dict = {};  // 逻辑控制组件对应的Sortable对象，key是logic_controller_id, value是Sortable对象
let element_case_instance_dict = {};  // 存放案例组件数据对象, key是case_id, value是组件element对象
let element_logic_controller_dict = {};  // 存放逻辑控制器对象, key是logic_controller_id, value是组件element对象
let element_tool_dict = {};  // 存放工具对象, key是tool_id, value是组件element对象
let element_case_first_show_flag = {};  // 标识案例对象是否是第一次打开, key是case_id, value是bool

// 界面元素
let $item_scene_group = $('.item-scene-group');
let $select_module = $('#select-module');
let $btn_start_module_test = $('#btn-start-module-test');
let $btn_stop_module_test = $('#btn-stop-module-test');
let $btn_mark = $('#btn-mark');
let $btn_clear_mark = $('#btn-clear-mark');
let $input_mark_text = $('#input-mark-text');
let $iframe_case = $('#iframe-case');
let $button_add_scene = $('#button-add-scene');
let $div_case_names = $('.case-name');
let $div_scene_names = $('.scene-name');
let $div_tool_names = $('.tool-name');
let $div_logic_controller_contents = $('.logic-controller-content');
let $div_scene_config = $('#div-scene-config');
let $input_module_id = $('#input-module-id');
let $no_scene_tip = $('#no-scene-tip');
let $modal_element_copy_tree = $('#modal-element-copy-tree');
let $select_project = $('#modal-element-copy-tree #select-project');
let $btn_element_copy = $('#btn-element-copy');
let $div_container_element = $('#div-container-element');
let $div_element_data_load_spinner = $('#element-data-load-spinner');
let $div_element_blank = $('.element-blank');
let div_card_scene_navigation = document.getElementById('scene-navigation');

// 注册WebSocket事件
// user_socket定义在base.html中，每次加载网页会创建
// user_socket.emit('new message', '客户端发送一个消息'); // 发送事件， 传入消息正文
// user_socket.on('new response', function (message) {
//    console.log(message);
// });
// 测试结果
user_socket.on('DISPATCHER_RESULT', function (data) {
    updateCaseDispatcherResult(data.id, data.result);
});
// 调度开始
user_socket.on('DISPATCHER_BEGIN', function (data) {
    dispatcher_id = data.id;
    if (data.type === 'module'){
        moduleDispatcherRunning();
        // message("模块测试启动成功", "success");
        message(`<a class="text-left" target="_blank" href='/report/detail/${data.report_id}' style="text-decoration:underline;">模块测试启动成功，点击跳转到编号${data.report_id}报告</a>`, "success");
    }
});
// 调度结束
user_socket.on('DISPATCHER_END', function (data) {
    dispatcher_id = null;
    if (data.type === 'module'){
        if (data.end_type === '成功'){
            message("模块测试执行完成", "success");
        }else if (data.end_type === '错误'){
            message("模块测试执行出现错误, 请查看结果日志", "error");
        }else if (data.end_type === '终止'){
            message("模块测试执行已中止", "success");
        }else{
            message("模块测试执行结束", "warning");
        }
        moduleDispatcherStoppedFinished();
    }
});

// 测试场景控件可拖拽
function SortableSceneGroup() {
    let divItemSceneGroups = document.getElementsByClassName('item-scene-group');

    $.each(divItemSceneGroups, function (index, divItemSceneGroup) {
        new Sortable(divItemSceneGroup, {
            group: 'sceneGroup', // set both lists to same group
            animation: 150,
            ghostClass: 'bg-sortable-ghost',  // 被拖拽时添加的类
            onEnd: function (evt) {  // 结束拖拽触发
                let to = evt.to;  // 被拖拽到的列表
                let to_module_id = $(to).data('module-id');
                let to_scene_id_arr = [];  // 被拖拽后列表中的场景id, 按照界面展示排序
                $.each($(to).children('.item-scene'), function (index, divItemScene) {
                    to_scene_id_arr[index] = $(divItemScene).data('scene-id');
                });
                $.ajax({
                    type: 'POST',
                    url: '/ajax/scene/drag_scene',
                    data: {
                        module_id: to_module_id,
                        scene_id_arr: JSON.stringify(to_scene_id_arr),
                    },
                    success: function (data, status, xhr) {
                        if (data.error_no === 0){

                        }else{
                            message("测试场景拖拽后台更新失败: " + data.error_msg, "error");
                        }
                    }
                })
            },
        })
    });
}

// 案例/工具组件与逻辑组件可嵌套拖拽
function SortableNestedElement() {
    sortable_nested_instance_dict = {};
    let divSortableNestedElements = document.getElementsByClassName('nested-sortable');

    $.each(divSortableNestedElements, function (index, divSortableNestedElement) {
        let logic_controller_id = $(divSortableNestedElement).data('logic-controller-id');
        sortable_nested_instance_dict[logic_controller_id] = new Sortable(divSortableNestedElement, {
            group: 'nested', // set both lists to same group
            animation: 150,
            fallbackOnBody: true,
            swapThreshold: 0.65,
            store:{
                set: function (sortable) {
                    let order_array = sortable.toArray();
                    let el = sortable.el;
                    // let logic_controller_type = null;
                    let logic_controller_id = $(el).data('logic-controller-id');
                    // if ($(el).hasClass('nested-sortable') && $(el).hasClass('scene-controller')){
                    //     logic_controller_type = '场景控制器';
                    // }
                    $.ajax({
                        type: 'POST',
                        url: '/ajax/scene/drag_element',
                        data: {
                            logic_controller_id: logic_controller_id,
                            order_array: JSON.stringify(order_array),
                        },
                        success: function (data, status, xhr) {
                            if (data.error_no === 0){

                            }else{
                                message("组件拖拽后台更新失败: " + data.error_msg, "error");
                            }
                        }
                    })
                }
            }
        });
    });
}

// 跳转到指定的测试模块
function jumpToModule(event) {
    let module_id = event.target.value;
    window.location.href="/scene/?module_id=" + module_id;
}

// 执行当前模块测试
function startModuleTest() {
    let $item_cases = $('.item-case');
    $item_cases.removeClass('item-case-dispatcher-result-success');
    $item_cases.removeClass('item-case-dispatcher-result-failure');
    $item_cases.removeClass('item-case-dispatcher-result-error');
    $item_cases.removeClass('item-case-dispatcher-result-abort');
    $.ajax({
        type: 'POST',
        url: '/ajax/module/test/start',
        data: {
            module_id: $input_module_id.val(),
        },
        success: function (data, status, xhr) {
            if (data.error_no === 0){
                // message("模块测试启动成功");
                // $btn_start_module_test.attr('disabled', true);
                // $btn_stop_module_test.attr('disabled', '');
            }else{
                message("模块测试启动失败: " + data.error_msg, "error");
                moduleDispatcherStoppedFinished();
            }
        }
    });
    moduleDispatcherStarting();
}

// 终止当前模块测试
function stopModuleTest() {
    $.ajax({
        type: 'POST',
        url: '/ajax/module/test/stop',
        data: {
            module_id: $input_module_id.val(),
            dispatcher_id: dispatcher_id,
        },
        success: function (data, status, xhr) {
            if (data.error_no === 0){
                // message("模块测试终止成功");
                // $btn_stop_module_test.attr('disabled', true);
                // $btn_start_module_test.attr('disabled', '');
            }else{
                message("模块测试终止失败: " + data.error_msg, "error");
            }
        }
    });
    moduleDispatcherStopping();
}

// 标记高亮展示
function mark() {
    // 清除标记
    clearMark();
    let text = $input_mark_text.val();
    $('*').mark(text);
    $.each(element_case_instance_dict, function (case_id, element) {
        let result = element.mark(text);
        if (result){
            $(`.item-case[data-case-id=${case_id}]`).addClass('marked');
        }
    });
    $.each(element_logic_controller_dict, function (logic_controller_id, element) {
        let result = element.mark(text);
        if (result){
            $(`.specific-logic-controller[data-logic-controller-id=${logic_controller_id}]`).addClass('marked');
        }
    });
    $.each(element_tool_dict, function (tool_id, element) {
        let result = element.mark(text);
        if (result){
            $(`.item-tool[data-tool-id=${tool_id}]`).addClass('marked');
        }
    });
}
// 清除标记
function clearMark() {
    $('*').unmark();
    $('.item-case').removeClass('marked');
    $('.specific-logic-controller').removeClass('marked');
    $('.item-tool').removeClass('marked');
}

// 添加新的场景
function addScene() {
    $.ajax({
        type: 'POST',
        url: '/ajax/scene/add',
        data: {
            module_id: $input_module_id.val(),
        },
        success: function (data, status, xhr) {
            if (data.error_no === 0){
                let newSceneHtml = data.scene_html;
                $div_scene_config.append(newSceneHtml);
                $no_scene_tip.css('display', 'none');
                tippyBtnScene();
                tippyBtnAddCase();
                SortableNestedElement();
                message("新增测试场景成功", "success");
                addSceneElement(data.scene_id)
            }else{
                message("新增测试场景失败: " + data.error_msg, "error");
            }
        },
    });
}

// 添加新的请求组件
function addCase(scene_id, case_type) {
    $.ajax({
        type: 'POST',
        url: '/ajax/case/add',
        data: {
            scene_id: scene_id,
            case_type: case_type,
        },
        success: function (data, status, xhr) {
            if (data.error_no === 0){
                let newCaseHtml = data.case_html;
                $('#item-scene-' + scene_id).append(newCaseHtml);
                tippyCaseName();
                tippyBtnCase();
                message("新增测试案例成功", "success");
                addCaseElement(data.case_id, case_type)
            }else{
                message("新增测试案例失败: " + data.error_msg, "error");
            }
        },
    });
}

// 添加新的工具组件
function addTool(parent_logic_controller_id, tool_type) {
    $.ajax({
        type: 'POST',
        url: '/ajax/tool/add',
        data: {
            parent_logic_controller_id: parent_logic_controller_id,
            tool_type: tool_type,
        },
        success: function (data, status, xhr) {
            if (data.error_no === 0){
                let newToolHtml = data.tool_html;
                $(`.nested-sortable[data-logic-controller-id=${parent_logic_controller_id}]`).append(newToolHtml);
                tippyToolName();
                tippyBtnTool();
                message("新增工具成功", "success");
                addToolElement(data.tool_id)
            }else{
                message("新增工具失败: " + data.error_msg, "error");
            }
        },
    });
}

// 添加逻辑组件
function addLogicController(parent_logic_controller_id, logic_controller_type) {
    // 逻辑控制器添加时都会默认添加在SceneController(场景控制器下面)
    $.ajax({
        type: 'POST',
        url: '/ajax/logic_controller/add',
        data: {
            parent_logic_controller_id: parent_logic_controller_id,
            logic_controller_type: logic_controller_type,
        },
        success: function (data, status, xhr) {
            if (data.error_no === 0){
                let newLogicControllerHtml = data.logic_controller_html;
                $('.nested-sortable[data-logic-controller-id=' + parent_logic_controller_id + ']' ).append(newLogicControllerHtml);
                message("逻辑控制器组件新增成功", "success");
                SortableNestedElement();
                tippyBtnLogicController();
                addLogicControllerElement(data.logic_controller_id);
            }else{
                message("逻辑控制器组件新增失败: " + data.error_msg, "error");
            }
        },
    });
}

// 展示案例组件复制对话框
function showElementCopyModal(scene_id) {
    reloadElementCopyTree(project_id);
    $modal_element_copy_tree.modal('show');
    $btn_element_copy.data('scene-id', scene_id);
}

// 渲染项目案例组件节点树
function renderElementCopyTree() {
    let elementCopyTree = null;

    $('#element-copy-tree').fancytree({
        // 如果是false则页面最初加载时，未展开的节点将不会生成dom元素，如果是true则会生成dom元素。
        activeVisible: true, // Make sure, active nodes are visible (expanded)
        // 无障碍属性
        aria: true, // Enable WAI-ARIA support
        // 使用键盘切换时会自动activate一个node
        autoActivate: true, // Automatically activate a node when it is focused using keyboard
        // 只允许有一个节点展开
        autoCollapse: false, // Automatically collapse all siblings, when a node is expanded
        // 自动滚动到可见区域
        autoScroll: true, // Automatically scroll nodes into visible area
        // click: function (event, data){
        //     let node = data.node;
        //     let element_type = node.data.element_type;
        //     let dispatcher_detail_id = node.data.dispatcher_detail_id;
        //     let id = element_type.toLowerCase() + '-' + dispatcher_detail_id;
        //     $('.report-detail-data').css('display', 'none');
        //     $('#' + id).css('display', '');
        // },
        // 点击folder node时触发的行为
        clickFolderMode: 4, // 1:activate, 2:expand, 3:activate and expand, 4:activate (dblclick expands)
        // 展示复选框
        checkbox: true, // Show check boxes
        // 复选框自动隐藏
        checkboxAutoHide: undefined, // Display check boxes on hover only
        debugLevel: 2, // 0:quiet, 1:errors, 2:warnings, 3:infos, 4:debug
        disabled: false, // Disable control
        focusOnSelect: false, // Set focus when node is checked by a mouse click
        // filter: {  // override default settings
        //     autoExpand: true,  // 匹配到节点时展开
        //     counter: true, // 在父节点上展示匹配到子节点的数量
        //     mode: "hide"  // "dimm": Grayout unmatched nodes, "hide": remove unmatched nodes
        // },
        // extensions: ["filter"],  // 启动拓展插件
        escapeTitles: false, // Escape `node.title` content for display
        // 是否生成id
        generateIds: true, // Generate id attributes like <span id='fancytree-id-KEY'>
        // id前缀
        idPrefix: "ft_", // Used to generate node idÂ´s like <span id='fancytree-id-<key>'>
        // 是否展示图标  Display node icons
        icon: function (event, data) {
            let node = data.node;
            let element_type = node.data.element_type;
            let case_type = node.data.case_type;
            let logic_controller_type = node.data.logic_controller_type;
            let tool_type = node.data.tool_type;
            // let case_result = node.data.case_result;
            let resultSuffix = '';
            if (element_type === 'PROJECT') {
                return 'icon-project';
            }else if(element_type === 'MODULE') {
                return 'icon-module';
            }else if(element_type === 'SCENE') {
                return 'icon-scene';
            }else if(element_type === 'CASE'){
                if(case_type === 'HTTP'){
                    return 'icon-case-http' + resultSuffix;
                }else if(case_type === 'SQL'){
                    return 'icon-case-sql' + resultSuffix;
                }else if(case_type === 'SSH'){
                    return 'icon-case-ssh' + resultSuffix;
                }else if(case_type === 'DEBUG'){
                    return 'icon-case-debug' + resultSuffix;
                }
                return 'icon-case';
            }else if (element_type === 'LOGIC_CONTROLLER'){
                if(logic_controller_type === 'IF'){
                    return 'icon-if-controller';
                }else if(logic_controller_type === 'WHILE'){
                    return 'icon-while-controller';
                }else if(logic_controller_type === 'LOOP'){
                    return 'icon-loop-controller';
                }else if(logic_controller_type === 'SIMPLE'){
                    return 'icon-simple-controller';
                }
            }else if (element_type === 'TOOL'){
                if(tool_type === 'TIMER'){
                    return 'icon-tool-timer';
                }else if(tool_type === 'SCRIPT'){
                    return 'icon-tool-script';
                }else if(tool_type === 'VARIABLE_DEFINITION'){
                    return 'icon-tool-variable-definition';
                }else if(tool_type === 'HTTP_HEADER_MANAGER'){
                    return 'icon-tool-http-header-manager';
                }else if(tool_type === 'HTTP_COOKIE_MANAGER'){
                    return 'icon-tool-http-cookie-manager';
                }
            }else if(element_type === undefined) {
                return true;
            }
        },
        // icon的tooltip
        iconTooltip: function(event, data) {
            return data.node.title + " (" + data.node.key + ")";
        },
        // The tree widget was initialized, source data was loaded, visible nodes are rendered,
        // selection propagation applied, and node activated.
        init: function (event, data) {
            elementCopyTree = $.ui.fancytree.getTree('#element-copy-tree');
            elementCopyTree.visit(function (node) {
                // 节点全部展开
                node.setExpanded(true);
            });
            // 默认active根节点
            let elementCopyNode = elementCopyTree.rootNode.children[0];
            elementCopyNode.setActive();
        },
        // 使用键盘导航
        keyboard: true, // Support keyboard navigation
        keyPathSeparator: "/", // Used by node.getKeyPath() and tree.loadKeyPath()
        // root 节点不可折叠
        minExpandLevel: 1, // 1: root node is not collapsible
        // 当tree loader未返回数据时显示一个消息
        nodata: true, // Display a special message when the tree loader returned no data (default: true)
        // 数据后处理
        postProcess: function(event, data){
            let response = data.response;
            if (response.error_no === -1){  // 该接口只有错误应答带error_no, 正常数据返回没有error_no
                message("查询项目案例节点树失败: " + response.error_msg, "error")
            }
        },
        // 通过输入首字母快速定位
        quicksearch: true, // Navigate to next node by typing the first letters
        rtl: false, // Enable RTL (right-to-left) mode
        // 初始化数据源, 打开页面时先不要加载数据，打开对话框时再加载
        source: null,
        // source: {
        //     type: 'POST',
        //     url: '/ajax/project/tree/get',
        //     data: {
        //         project_id: project_id,
        //     }
        // },
        selectMode: 2, // 1:single, 2:multi, 3:multi-hier
        // tree可以被tab键选中
        tabindex: "0", // Whole tree behaves as one single control
        // 使用tab键切换node
        titlesTabbable: true, // Node titles can receive keyboard focus
        // node节点tooltip
        tooltip: function (event, data) {
            return 'this is node tooltip'
        }, // Use title as tooltip (also a callback could be specified)
        // https://wwwendt.de/tech/fancytree/doc/jsdoc/global.html#FancytreeOptions
    });
}

// 重新加载指定项目案例组件节点树
function reloadElementCopyTree(project_id) {
    $.ajax({
        type: 'POST',
        url: '/ajax/project/tree/get',
        data: {
            project_id: project_id,
        },
        success: function (data, status, xhr) {
            if (data.error_no === -1){
                message("查询项目案例节点树失败: " + data.error_msg, "error");
            }else{
                $.ui.fancytree.getTree('#element-copy-tree').clear();
                $.ui.fancytree.getTree('#element-copy-tree').reload(data);
            }
        },
    })
}

// 选择列表中的项目，展示该项目下所有案例组件
function selectProjectToCopy() {
    let project_id = $(this).val();
    reloadElementCopyTree(project_id);
}

// 从项目中复制选择的案例
function copyElementFromProjectTree() {
    let scene_id = $btn_element_copy.data('scene-id');
    let elementCopyTree = $.ui.fancytree.getTree('#element-copy-tree');
    let selected_nodes = elementCopyTree.getSelectedNodes(false);
    let promise_array = [];
    let $div_scene_controller = $('.scene-controller[data-scene-id='+ scene_id +']');
    let parent_logic_controller_id = $div_scene_controller.data('logic-controller-id');
    $.each(selected_nodes, function (index, node) {
        if (node.data.element_type === 'CASE'){
            let case_id = node.data.element_id;
            promise_array.push(copyCase(case_id, scene_id, parent_logic_controller_id));
        }else if(node.data.element_type === 'LOGIC_CONTROLLER'){
            let logic_controller_id = node.data.element_id;
            promise_array.push(copyLogicController(logic_controller_id, parent_logic_controller_id, scene_id));
        }else if(node.data.element_type === 'TOOL'){
            let tool_id = node.data.element_id;
            promise_array.push(copyTool(tool_id, parent_logic_controller_id));
        }
    });
    Promise.all(promise_array).then((result) => {
        // console.log('then');
        // console.log(result);               // [['成功了', 'success'], ...]
        let sortable = sortable_nested_instance_dict[parent_logic_controller_id];
        let order_array = sortable.toArray();
        $.ajax({
            type: 'POST',
            url: '/ajax/scene/drag_element',
            data: {
                logic_controller_id: parent_logic_controller_id,
                order_array: JSON.stringify(order_array),
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){

                }else{
                    message("案例组件后台更新失败: " + data.error_msg, "error");
                }
            }
        })
    }).catch((error) => {
        // console.log('catch');
        // console.log(error);
    }).finally(() => {
        // console.log('finally');
    });
    $modal_element_copy_tree.modal('hide');
}

// 给场景设置按钮添加弹出提示控件
function tippyBtnScene() {
    let $btnScenes = $('.btn-scene');
    $.each($btnScenes, function (index, btnScene) {
        if (btnScene._tippy === undefined){  // 当控件未设置tippy时才添加弹出提示，否则会出现多个弹出框
            tippy(btnScene, {
                trigger: 'click',
                hideOnClick: true,
                placement: 'bottom',
                allowHTML: true,
                interactive: true,
                content: function (){
                    return $(btnScene).next().html();
                },
                // appendTo: 'parent',
                // appendTo: () => document.body,
                appendTo: div_card_scene_navigation,
                zIndex: 0,  // 默认9999 当有模态框显示时，提示框依然会展示在最上层且可以操作点击，因此更改zIndex为0，将其放置于模态框下层
                theme: 'light',
            });
        }
    })
}
// 为新增场景按钮添加弹出提示控件
function tippyBtnAddScene() {
    tippy($button_add_scene[0], {
        trigger: 'mouseenter focus',
        placement: 'top',
        content: '点击创建新的测试场景',
    });
}
// 为逻辑控制器组件添加弹出控件
function tippyBtnLogicController() {
    let $btnLogicControllers = $('.btn-logic-controller');
    $.each($btnLogicControllers, function (index, btnLogicController) {
        if (btnLogicController._tippy === undefined){  // 当控件未设置tippy时才添加弹出提示，否则会出现多个弹出框
            tippy(btnLogicController, {
                trigger: 'click',
                hideOnClick: true,
                placement: 'bottom',
                allowHTML: true,
                interactive: true,
                content: function (){
                    return $(btnLogicController).next().html();
                },
                // appendTo: 'parent',
                // appendTo: () => document.body,
                appendTo: div_card_scene_navigation,
                zIndex: 0,  // 默认9999 当有模态框显示时，提示框依然会展示在最上层且可以操作点击，因此更改zIndex为0，将其放置于模态框下层
                theme: 'light',
            });
        }
    })
}
// 为新增测试案例组件按钮添加弹出框
function tippyBtnAddCase() {
    let $btnAddCases = $('.btn-add-case');
    $.each($btnAddCases, function (index, btnAddCase) {  // 当控件未设置tippy时才添加弹出提示，否则会出现多个弹出框
        if (btnAddCase._tippy === undefined){
            tippy(btnAddCase, {
                trigger: 'mouseenter focus',
                placement: 'top',
                content: '点击添加测试案例组件',
            });
            tippy(btnAddCase, {
                trigger: 'click',
                hideOnClick: true,
                placement: 'right',
                allowHTML: true,
                interactive: true,
                content: function (){
                    return $(btnAddCase).next().html();
                },
                // appendTo: 'parent',
                appendTo: () => document.body,
                // appendTo: div_card_scene_navigation,
                // zIndex默认9999 当有模态框显示时，提示框依然会展示在最上层且可以操作点击，因此更改zIndex为0，将其放置于模态框下层
                // 但如果设置为0时，handsontable表格会和tippy框样式重叠，尝试了多个zIndex数值，发现大于200可以解决重叠问题
                zIndex: 200,
                theme: 'light',
                maxWidth: 'none',
            });
            // 由于前端使用的控件是导航（http://code.z01.com/v4/components/navs.html）
            // 必须在tippy后将其删除否则会出现id重复导致无法切换的问题
            $(btnAddCase).next().remove();
        }
    })
}
// 为案例设置按钮添加弹出提示控件
function tippyBtnCase() {
    let $btnCases = $('.btn-case');
    $.each($btnCases, function (index, btnCase) {
        if (btnCase._tippy === undefined){  // 当控件未设置tippy时才添加弹出提示，否则会出现多个弹出框
            tippy(btnCase, {
                trigger: 'click',
                hideOnClick: true,
                placement: 'bottom',
                allowHTML: true,
                interactive: true,
                content: function (){
                    return $(btnCase).next().html();
                },
                // appendTo: 'parent',
                // appendTo: () => document.body,
                appendTo: div_card_scene_navigation,
                zIndex: 0,  // 默认9999 当有模态框显示时，提示框依然会展示在最上层且可以操作点击，因此更改zIndex为0，将其放置于模态框下层
                theme: 'light',
            });
        }
    })
}
// 为场景名称添加提示框
function tippySceneName() {
let $divSceneNames = $('.scene-name');
    $.each($divSceneNames, function (index, divSceneName) {
        if (divSceneName._tippy === undefined){  // 判断当前控件上是否已经设置了tippy，=undefined表示未设置
            tippy(divSceneName, {
                trigger: 'mouseenter focus',
                placement: 'top',
                theme: 'translucent',
                followCursor: 'horizontal',
                content: $(divSceneName).text(),
            });
        }else{
            divSceneName._tippy.setContent($(divSceneName).text());
        }
    })
}
// 为案例组件案例名称增加提示框
function tippyCaseName() {
    let $divCaseInfos = $('.case-info');
    $.each($divCaseInfos, function (index, divCaseInfo) {
        if (divCaseInfo._tippy === undefined){  // 判断当前控件上是否已经设置了tippy，=undefined表示未设置
            tippy(divCaseInfo, {
                trigger: 'mouseenter focus',
                placement: 'top',
                theme: 'translucent',
                followCursor: 'horizontal',
                content: $(divCaseInfo).children('.case-name').text(),
            });
        }else{
            divCaseInfo._tippy.setContent($(divCaseInfo).children('.case-name').text());
        }
    })
}
// 为逻辑控制内容增加提示框
function tippyLogicControllerContent() {
let $divLogicControllerContents = $('.logic-controller-content');
    $.each($divLogicControllerContents, function (index, divLogicControllerContent) {
        if (divLogicControllerContent._tippy === undefined){  // 判断当前控件上是否已经设置了tippy，=undefined表示未设置
            tippy(divLogicControllerContent, {
                trigger: 'mouseenter focus',
                placement: 'top',
                theme: 'translucent',
                followCursor: 'horizontal',
                content: $(divLogicControllerContent).text(),
            });
        }else{
            divLogicControllerContent._tippy.setContent($(divLogicControllerContent).text());
        }
    })
}
// 为工具设置按钮添加弹出提示控件
function tippyBtnTool() {
    let $btnTools = $('.btn-tool');
    $.each($btnTools, function (index, btnTool) {
        if (btnTool._tippy === undefined){  // 当控件未设置tippy时才添加弹出提示，否则会出现多个弹出框
            tippy(btnTool, {
                trigger: 'click',
                hideOnClick: true,
                placement: 'bottom',
                allowHTML: true,
                interactive: true,
                content: function (){
                    return $(btnTool).next().html();
                },
                // appendTo: 'parent',
                // appendTo: () => document.body,
                appendTo: div_card_scene_navigation,
                zIndex: 0,  // 默认9999 当有模态框显示时，提示框依然会展示在最上层且可以操作点击，因此更改zIndex为0，将其放置于模态框下层
                theme: 'light',
            });
        }
    })
}
// 为工具组件名称增加提示框
function tippyToolName() {
    let $divToolNames = $('.tool-name');
    $.each($divToolNames, function (index, divToolName) {
        if (divToolName._tippy === undefined){  // 判断当前控件上是否已经设置了tippy，=undefined表示未设置
            tippy(divToolName, {
                trigger: 'mouseenter focus',
                placement: 'top',
                theme: 'translucent',
                followCursor: 'horizontal',
                content: $(divToolName).text(),
            });
        }else{
            divToolName._tippy.setContent($(divToolName).text());
        }
    })
}

// 切换场景收缩按钮的icon
// TODO 有点小问题 就是快速点击折叠过程中切换类会导致错误展示icon
function changeBtnCollapseIcon(which) {
    if ($(which).hasClass('btn-fold')){
        $(which).removeClass('btn-fold').addClass('btn-unfold');
    }else if ($(which).hasClass('btn-unfold')){
        $(which).removeClass('btn-unfold').addClass('btn-fold');
    }
}

// 删除指定的测试场景
function deleteScene(id) {
    Swal.fire({
        title: '确定删除 ' + id + ' 测试场景吗？',
        text: "删除后将无法恢复!",
        icon: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#3085d6',
        confirmButtonText: '确定',
        cancelButtonColor: '#d33',
        cancelButtonText: '取消',
    }).then((result) => {
        if (result.isConfirmed) {
            $.ajax({
                type: 'POST',
                url: '/ajax/scene/delete',
                data: {
                    id: id,
                },
                success: function (data, status, xhr) {
                    if (data.error_no === 0){
                        let $div_card_scene = $(".item-scene[data-scene-id="+ id +"]");
                        $div_card_scene.remove();
                        // message("删除测试场景成功", "success");
                        Swal.fire({
                            title: '删除!',
                            text: '测试场景' + id + '已被删除.',
                            icon: 'success',
                        });
                        // 删除所有组件Dom
                        $(`.element-scene[data-scene-id=${id}]`).remove();
                        $.each($div_card_scene.find('.item-case'), function (index, itemCase) {
                            let case_id = $(itemCase).data('case-id');
                            $(`.element-case[data-case-id=${case_id}]`).remove();
                        });
                        $.each($div_card_scene.find('.item-tool'), function (index, itemTool) {
                            let tool_id = $(itemTool).data('tool-id');
                            $(`.element-tool[data-tool-id=${tool_id}]`).remove();
                        });
                        $.each($div_card_scene.find('.logic-controller'), function (index, itemLoigcController) {
                            let logic_controller_id = $(itemLoigcController).data('logic-controller-id');
                            $(`.element-logic-controller[data-logic-controller-id=${logic_controller_id}]`).remove();
                        });
                        // $iframe_case.attr('src','/blank');
                    }else{
                        message("删除测试场景失败: " + data.error_msg, "error");
                    }
                },
            });
        }
    });
}
// 禁用指定的测试场景
function forbiddenScene(id) {
    let $divSceneName = $('.item-scene[data-scene-id='+ id +']').find('.scene-name');
    if ($divSceneName.hasClass('div-forbidden')){
        $.ajax({
            type: 'POST',
            url: '/ajax/scene/forbidden',
            data: {
                id: id,
                type: 'enable',
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    $divSceneName.removeClass('div-forbidden');
                }else{
                    message("启用测试场景组件失败: " + data.error_msg, "error");
                }
            },
        });
    }else{
        $.ajax({
            type: 'POST',
            url: '/ajax/scene/forbidden',
            data: {
                id: id,
                type: 'forbidden',
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    $divSceneName.addClass('div-forbidden');
                }else{
                    message("禁用测试场景组件失败: " + data.error_msg, "error");
                }
            },
        });
    }
}
// 复制指定的测试场景
function copyScene(id) {
    $.ajax({
        type: 'POST',
        url: '/ajax/scene/copy',
        data: {
            id: id,
        },
        success: function (data, status, xhr) {
            if (data.error_no === 0){
                let copySceneHtml = data.scene_html;
                $div_scene_config.append(copySceneHtml);
                tippyBtnScene();
                tippyBtnAddCase();
                SortableNestedElement();
                tippyCaseName();
                tippyBtnCase();
                tippyToolName();
                tippyBtnTool();
                tippyBtnLogicController();
                traverseSpecifiedSceneElementAndLoadDom($(copySceneHtml));
                traverseSpecifiedLogicControllerElementAndLoadDom($(copySceneHtml).find('.logic-controller'));
                traverseSpecifiedCaseElementAndLoadDom($(copySceneHtml).find('.item-case'));
                traverseSpecifiedToolElementAndLoadDom($(copySceneHtml).find('.item-tool'));
                message("测试场景复制成功", "success");
            }else{
                message("测试场景复制失败: " + data.error_msg, "error");
            }
        },
    });
}

// iframe展示测试场景页面
// function showScene(id) {
//     // 样式展示
//     let $divItemCases = $('.item-case');
//     $divItemCases.removeClass('item-case-active');
//     let $itemSceneHeaders = $('.item-scene-header-active');
//     $itemSceneHeaders.removeClass('item-scene-header-active');
//     let $itemSceneHeader = $('.item-scene-header[data-scene-id='+ id +']');
//     $itemSceneHeader.addClass('item-scene-header-active');
//     // iframe跳转
//     $iframe_case.attr('src','/scene/setting/' + id);
// }
function showScene(scene_id) {
    // 将其他组件Dom隐藏
    $('.element-data').css('display', 'none');
    // 样式展示
    navigationElementRemoveActiveClass();
    let $itemSceneHeader = $(`.item-scene-header[data-scene-id=${scene_id}]`);
    $itemSceneHeader.addClass('active');
    $div_element_data_load_spinner.css('display', '');
    setTimeout(function() {
        // 找到需要展示的场景Dom
        $.wait(
            `.element-scene[data-scene-id=${scene_id}]`,
            function ($element) {
                // $div_element_data_load_spinner.css('display', 'none');
                $('.element-data').css('display', 'none');  // 防止在等待过程中又有其他组件展示
                $div_element_data_load_spinner.css("cssText", "display: none !important;");
                $element.css('display', '');
            },
            1000,
            500,
        );
    }, 100);
}

// 删除指定的逻辑控制器
function deleteLogicController(logic_controller_id) {
    Swal.fire({
        title: '确定删除 ' + logic_controller_id + ' 逻辑控制器吗？',
        text: "删除后将无法恢复!",
        icon: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#3085d6',
        confirmButtonText: '确定',
        cancelButtonColor: '#d33',
        cancelButtonText: '取消',
    }).then((result) => {
        if (result.isConfirmed) {
            $.ajax({
                type: 'POST',
                url: '/ajax/logic_controller/delete',
                data: {
                    logic_controller_id: logic_controller_id,
                },
                success: function (data, status, xhr) {
                    if (data.error_no === 0){
                        let $div_logic_controller = $(".logic-controller[data-logic-controller-id="+ logic_controller_id +"]");
                        $div_logic_controller.remove();
                        Swal.fire({
                            title: '删除!',
                            text: '逻辑控制器' + logic_controller_id + '已被删除.',
                            icon: 'success',
                        });
                        // 删除所有组件Dom
                        $(`.element-logic-controller[data-logic-controller-id=${logic_controller_id}]`).remove();
                        $.each($div_logic_controller.find('.logic-controller'), function (index, itemLoigcController) {
                            let logic_controller_id = $(itemLoigcController).data('logic-controller-id');
                            $(`.element-logic-controller[data-logic-controller-id=${logic_controller_id}]`).remove();
                        });
                        $.each($div_logic_controller.find('.item-case'), function (index, itemCase) {
                            let case_id = $(itemCase).data('case-id');
                            $(`.element-case[data-case-id=${case_id}]`).remove();
                        });
                        $.each($div_logic_controller.find('.item-tool'), function (index, itemTool) {
                            let tool_id = $(itemTool).data('tool-id');
                            $(`.element-tool[data-tool-id=${tool_id}]`).remove();
                        });
                        // $iframe_case.attr('src','/blank');
                    }else{
                        message("删除逻辑控制器失败: " + data.error_msg, "error");
                    }
                },
            });
        }
    });
}
// 禁用指定的逻辑控制器
function forbiddenLogicController(logic_controller_id) {
    let $divLogicController = $('.logic-controller[data-logic-controller-id='+ logic_controller_id +']');
    let $spanLogicControllerType = $($divLogicController.find('.logic-controller-type')[0]);
    let $divLogicControllerContent = $($divLogicController.find('.logic-controller-content')[0]);
    if($spanLogicControllerType.hasClass('div-forbidden')){
        $.ajax({
            type: 'POST',
            url: '/ajax/logic_controller/forbidden',
            data: {
                logic_controller_id: logic_controller_id,
                type: 'enable',
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    $spanLogicControllerType.removeClass('div-forbidden');
                    $divLogicControllerContent.removeClass('div-forbidden');
                }else{
                    message("启用逻辑控制器组件失败: " + data.error_msg, "error");
                }
            },
        });
        }else{
            $.ajax({
                type: 'POST',
                url: '/ajax/logic_controller/forbidden',
                data: {
                    logic_controller_id: logic_controller_id,
                    type: 'forbidden',
                },
                success: function (data, status, xhr) {
                    if (data.error_no === 0){
                        $spanLogicControllerType.addClass('div-forbidden');
                        $divLogicControllerContent.addClass('div-forbidden');
                    }else{
                        message("禁用逻辑控制器组件失败: " + data.error_msg, "error");
                    }
                },
            });
        }
}
// 复制指定的逻辑控制器
function copyLogicController(logic_controller_id, parent_logic_controller_id, scene_id) {
    let $parent_logic_controller = $('.nested-sortable[data-logic-controller-id=' + parent_logic_controller_id + ']');
    let promise = new Promise((resolve, reject) => {
        $.ajax({
            type: 'POST',
            url: '/ajax/logic_controller/copy',
            data: {
                logic_controller_id: logic_controller_id,
                parent_logic_controller_id: parent_logic_controller_id,
                scene_id: scene_id,
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0) {
                    $parent_logic_controller.append(data.logic_controller_html);
                    SortableNestedElement();
                    tippyCaseName();
                    tippyBtnCase();
                    tippyToolName();
                    tippyBtnTool();
                    tippyBtnLogicController();
                    traverseSpecifiedLogicControllerElementAndLoadDom($(data.logic_controller_html));
                    traverseSpecifiedLogicControllerElementAndLoadDom($(data.logic_controller_html).find('.logic-controller'));
                    traverseSpecifiedCaseElementAndLoadDom($(data.logic_controller_html).find('.item-case'));
                    traverseSpecifiedToolElementAndLoadDom($(data.logic_controller_html).find('.item-tool'));
                    resolve(['成功了', 'success']);  // 也可以传递其他类型参数
                } else {
                    message("复制逻辑控制器组件失败: " + data.error_msg, "error");
                }
            },
        })
    });
    return promise;
}
// 复制当前逻辑控制器
function copyLogicControllerSelf(self) {
    let logic_controller_id = $(self).data('logic-controller-id');
    // 找到当前逻辑控制器所在的父逻辑控制器
    let $div_logic_controller = $('.logic-controller[data-logic-controller-id=' + logic_controller_id + ']');
    let $div_parent_logic_controller = $div_logic_controller.parent();
    let parent_logic_controller_id = $div_parent_logic_controller.data('logic-controller-id');
    // 找到当前案例所在的场景控制器
    let $div_scene_controller = $div_logic_controller.parents('.scene-controller.nested-sortable');
    let scene_id = $div_scene_controller.data('scene-id');
    copyLogicController(logic_controller_id, parent_logic_controller_id, scene_id);
}

// 点击specific-logic-controller逻辑控制器组件事件响应函数
function clickLogicController(event) {
    let currentTarget = event.currentTarget;
    let target = event.target;
    let logic_controller_id = $(currentTarget).data('logic-controller-id');
    if ($(currentTarget).find('.logic-controller-content').hasClass('div-forbidden')){
        return null;
    }else if ($(target).hasClass('btn-logic-controller')){
        return null;
    }else if ($(target).hasClass('btn-unfold')){
        return null;
    }else if ($(target).hasClass('btn-fold')){
        return null;
    }else {
        showLogicController(logic_controller_id);
    }
}
// 展示逻辑控制器
// function showLogicController(logic_controller_id) {
//     // iframe跳转
//     $iframe_case.attr('src','/logic_controller/' + logic_controller_id);
// }
function showLogicController(logic_controller_id) {
    // 将其他组件Dom隐藏
    $('.element-data').css('display', 'none');
    // 样式展示
    navigationElementRemoveActiveClass();
    $(`.specific-logic-controller[data-logic-controller-id=${logic_controller_id}]`).addClass('active');
    $div_element_data_load_spinner.css('display', '');
    setTimeout(function() {
        // 找到需要展示的场景Dom
        $.wait(
            `.element-logic-controller[data-logic-controller-id=${logic_controller_id}]`,
            function ($element) {
                // $div_element_data_load_spinner.css('display', 'none');
                $('.element-data').css('display', 'none');  // 防止在等待过程中又有其他组件展示
                $div_element_data_load_spinner.css("cssText", "display: none !important;");
                $element.css('display', '');
            },
            1000,
            500,
        );
    }, 100);
}

// 删除指定的案例组件
function deleteCase(id) {
    let case_id = id;
    let $divItemCase = $('.item-case[data-case-id='+ case_id +']');

    Swal.fire({
        title: '确定删除 案例' + case_id + ' 吗?',
        text: '删除后将无法恢复!',
        icon: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#3085d6',
        cancelButtonColor: '#d33',
        confirmButtonText: '确定',
        cancelButtonText: '取消',
    }).then((result) => {
        if (result.value) {
            $.ajax({
                type: 'POST',
                url: '/ajax/case/delete',
                data: {
                    case_id: case_id,
                },
                success: function (data, status, xhr) {
                    if (data.error_no === 0){
                        // message("删除案例成功", "success");
                        Swal.fire({
                            title: '删除!',
                            text: '案例' + case_id + '已被删除.',
                            icon: 'success',
                        });
                        $divItemCase.remove();
                        // 删除对应案例Dom
                        $(`.element-case[data-case-id=${case_id}]`).remove();
                        // $iframe_case.attr('src','/blank');
                    }else{
                        message("删除案例失败: " + data.error_msg, "error");
                    }
                },
            });
        }
    });
}
// 禁用测试案例组件
function forbiddenCase(id) {
    let $divItemCase=  $('.item-case[data-case-id='+ id +']');
    let $spanCaseType = $divItemCase.children('.case-type');
    let $spanCaseMethod = $divItemCase.children('.case-method');
    let $spanCaseInfo = $divItemCase.find('.case-info');
    if ($spanCaseType.hasClass('div-forbidden')){
        $.ajax({
            type: 'POST',
            url: '/ajax/case/forbidden',
            data: {
                id: id,
                type: 'enable',
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    $spanCaseType.removeClass('div-forbidden');
                    $spanCaseMethod.removeClass('div-forbidden');
                    $spanCaseInfo.removeClass('div-forbidden');
                }else{
                    message("启用测试案例组件失败: " + data.error_msg, "error");
                }
            },
        });
    }else{
        $.ajax({
            type: 'POST',
            url: '/ajax/case/forbidden',
            data: {
                id: id,
                type: 'forbidden',
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    $spanCaseType.addClass('div-forbidden');
                    $spanCaseMethod.addClass('div-forbidden');
                    $spanCaseInfo.addClass('div-forbidden');
                }else{
                    message("禁用测试案例组件失败: " + data.error_msg, "error");
                }
            },
        });
    }
}
// 复制测试案例组件
function copyCase(case_id, scene_id, logic_controller_id) {
    // case_id: 被复制的case.id
    // scene_id: 复制到的scene.id
    // logic_controller_id: 复制到的逻辑控制器id
    let $div_logic_controller = $('.nested-sortable[data-logic-controller-id=' + logic_controller_id + ']');
    let promise = new Promise((resolve, reject) => {
        $.ajax({
            type: 'POST',
            url: '/ajax/case/copy',
            data: {
                case_id: case_id,
                scene_id: scene_id,
                logic_controller_id: logic_controller_id,
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    let copyCaseHtml = data.case_html;
                    $div_logic_controller.append(copyCaseHtml);
                    tippyCaseName();
                    tippyBtnCase();
                    traverseSpecifiedCaseElementAndLoadDom($(copyCaseHtml));
                    message("案例组件复制成功", "success");
                    resolve(['成功了', 'success']);  // 也可以传递其他类型参数
                }else{
                    message("案例组件复制失败: " + data.error_msg, "error");
                }
            },
        });
    });
    return promise;
}
// 复制当前案例
function copyCaseSelf(self) {
    let case_id = $(self).data('case-id');
    // 找到当前案例所在的父逻辑控制器
    let $div_case = $('.item-case[data-case-id=' + case_id + ']');
    let $div_logic_controller = $div_case.parent();
    let logic_controller_id = $div_logic_controller.data('logic-controller-id');
    // 找到当前案例所在的场景控制器
    let $div_scene_controller = $div_case.parents('.scene-controller.nested-sortable');
    let scene_id = $div_scene_controller.data('scene-id');
    copyCase(case_id, scene_id, logic_controller_id);
}

// iframe展示测试案例页面
// function showCase(id) {
//     // 样式展示
//     let $divItemCases = $('.item-case');
//     $divItemCases.removeClass('item-case-active');
//     let $itemSceneHeaders = $('.item-scene-header-active');
//     $itemSceneHeaders.removeClass('item-scene-header-active');
//     let $divItemCase = $('.item-case[data-case-id='+ id +']');
//     $divItemCase.addClass('item-case-active');
//     // iframe跳转
//     $iframe_case.attr('src','/case/' + id);
// }
function showCase(case_id, case_type) {
    // 将其他组件Dom隐藏
    $('.element-data').css('display', 'none');
    // 样式展示
    navigationElementRemoveActiveClass();
    $(`.item-case[data-case-id=${case_id}]`).addClass('active');
    $div_element_data_load_spinner.css('display', '');
    setTimeout(function() {
        // 找到需要展示的案例Dom
        $.wait(
            `.element-case[data-case-id=${case_id}]`,
            function ($element) {
                // $div_element_data_load_spinner.css('display', 'none');
                $('.element-data').css('display', 'none');  // 防止在等待过程中又有其他组件展示
                $div_element_data_load_spinner.css("cssText", "display: none !important;");
                $element.css('display', '');
                // invisible状态下ht不可被渲染，因此在这里渲染
                $(`#table-expectation-${case_id}`).handsontable('getInstance').render();
                if(case_type === 'HTTP'){
                    // 渲染ht
                    $(`#table-parameter-${case_id}`).handsontable('getInstance').render();
                    $(`#table-header-${case_id}`).handsontable('getInstance').render();
                    $(`#table-file-upload-${case_id}`).handsontable('getInstance').render();
                }
                if(!element_case_first_show_flag[case_id]){  // 只在第一次打开案例组件时渲染
                    // 渲染分割条
                    element_case_instance_dict[case_id].renderSplitter();
                    element_case_first_show_flag[case_id] = true;
                }
            },
            1000,
            500,
        );
    }, 100);
}
// 点击item-case案例组件事件响应函数
function clickItemCase(event) {
    let currentTarget = event.currentTarget;
    let target = event.target;
    let case_id = $(currentTarget).data('case-id');
    let case_type = $(currentTarget).data('case-type');
    if ($(currentTarget).find('.case-info').hasClass('div-forbidden')){
        return null;
    }else if ($(target).hasClass('btn-case')){
        return null;
    }else {
        showCase(case_id, case_type);
    }
}

// 展示案例调度执行结果
function updateCaseDispatcherResult(id, result) {
    let $item_case = $('.item-case[data-case-id=' + id + ']');
    $item_case.removeClass('item-case-dispatcher-result-success');
    $item_case.removeClass('item-case-dispatcher-result-failure');
    $item_case.removeClass('item-case-dispatcher-result-error');
    $item_case.removeClass('item-case-dispatcher-result-abort');
    // console.log(result);
    if (result === '成功'){
        $item_case.addClass('item-case-dispatcher-result-success');
    }else if (result === '失败') {
        $item_case.addClass('item-case-dispatcher-result-failure');
    }else if (result === '错误') {
        $item_case.addClass('item-case-dispatcher-result-error');
    }else if (result === '中止') {
        $item_case.addClass('item-case-dispatcher-result-abort');
    }
}

// 删除指定的工具组件
function deleteTool(tool_id) {
    let $divItemTool = $(`.item-tool[data-tool-id=${tool_id}]`);

    Swal.fire({
        title: `确定删除 工具${tool_id} 吗?`,
        text: '删除后将无法恢复!',
        icon: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#3085d6',
        cancelButtonColor: '#d33',
        confirmButtonText: '确定',
        cancelButtonText: '取消',
    }).then((result) => {
        if (result.value) {
            $.ajax({
                type: 'POST',
                url: '/ajax/tool/delete',
                data: {
                    tool_id: tool_id,
                },
                success: function (data, status, xhr) {
                    if (data.error_no === 0){
                        Swal.fire({
                            title: '删除!',
                            text: `工具${tool_id}已被删除.`,
                            icon: 'success',
                        });
                        $divItemTool.remove();
                        // 删除对应工具Dom
                        $(`.element-tool[data-tool-id=${tool_id}]`).remove();
                    }else{
                        message("删除工具失败: " + data.error_msg, "error");
                    }
                },
            });
        }
    });
}
// 禁用指定的工具组件
function forbiddenTool(tool_id) {
    let $divItemTool =  $(`.item-tool[data-tool-id=${tool_id}]`);
    let $spanToolType = $divItemTool.children('.tool-type');
    let $divToolName = $divItemTool.children('.tool-name');
    if ($divToolName.hasClass('div-forbidden')){
        $.ajax({
            type: 'POST',
            url: '/ajax/tool/forbidden',
            data: {
                tool_id: tool_id,
                type: 'enable',
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    $spanToolType.removeClass('div-forbidden');
                    $divToolName.removeClass('div-forbidden');
                }else{
                    message("启用工具组件失败: " + data.error_msg, "error");
                }
            },
        });
    }else{
        $.ajax({
            type: 'POST',
            url: '/ajax/tool/forbidden',
            data: {
                tool_id: tool_id,
                type: 'forbidden',
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    $spanToolType.addClass('div-forbidden');
                    $divToolName.addClass('div-forbidden');
                }else{
                    message("禁用工具组件失败: " + data.error_msg, "error");
                }
            },
        });
    }
}
// 复制指定的工具组件
function copyToolSelf(self) {
    let tool_id = $(self).data('tool-id');
    // 找到当前工具所在的父逻辑控制器
    let $div_logic_controller = $(`.item-tool[data-tool-id=${tool_id}]`).parent();
    let logic_controller_id = $div_logic_controller.data('logic-controller-id');
    copyTool(tool_id, logic_controller_id);
}
function copyTool(tool_id, logic_controller_id) {
    // tool_id: 被复制的tool.id
    // logic_controller_id: 复制到的逻辑控制器id
    let $div_logic_controller = $(`.nested-sortable[data-logic-controller-id=${logic_controller_id}]`);
    let promise = new Promise((resolve, reject) => {
        $.ajax({
            type: 'POST',
            url: '/ajax/tool/copy',
            data: {
                tool_id: tool_id,
                logic_controller_id: logic_controller_id,
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    let copyToolHtml = data.tool_html;
                    $div_logic_controller.append(copyToolHtml);
                    tippyToolName();
                    tippyBtnTool();
                    traverseSpecifiedToolElementAndLoadDom($(copyToolHtml));
                    message("工具组件复制成功", "success");
                    resolve(['成功了', 'success']);  // 也可以传递其他类型参数
                }else{
                    message("工具组件复制失败: " + data.error_msg, "error");
                }
            },
        });
    });
    return promise;
}
// 展示工具组件
function showTool(tool_id, tool_type) {
    // 将其他组件Dom隐藏
    $('.element-data').css('display', 'none');
    // 样式展示
    navigationElementRemoveActiveClass();
    $(`.item-tool[data-tool-id=${tool_id}]`).addClass('active');
    $div_element_data_load_spinner.css('display', '');
    setTimeout(function() {
        // 找到需要展示的工具Dom
        $.wait(
            `.element-tool[data-tool-id=${tool_id}]`,
            function ($element) {
                // $div_element_data_load_spinner.css('display', 'none');
                $('.element-data').css('display', 'none');  // 防止在等待过程中又有其他组件展示
                $div_element_data_load_spinner.css("cssText", "display: none !important;");
                $element.css('display', '');
                if(tool_type === 'VARIABLE_DEFINITION'){
                    $(`#table-variable-definition-${tool_id}`).handsontable('getInstance').render();
                }else if(tool_type === 'HTTP_HEADER_MANAGER'){
                    $(`#table-http-header-manager-${tool_id}`).handsontable('getInstance').render();
                }else if(tool_type === 'HTTP_COOKIE_MANAGER'){
                    $(`#table-http-cookie-manager-${tool_id}`).handsontable('getInstance').render();
                }
            },
            1000,
            500,
        );
    }, 100);
}
// 点击左侧导航工具组件响应函数
function clickTool(event) {
    let currentTarget = event.currentTarget;
    let target = event.target;
    let tool_id = $(currentTarget).data('tool-id');
    let tool_type = $(currentTarget).data('tool-type');
    if ($(currentTarget).find('.tool-name').hasClass('div-forbidden')){
        return null;
    }else if ($(target).hasClass('btn-tool')){
        return null;
    }else {
        showTool(tool_id, tool_type);
    }
}



// 查询模块调度信息
function getModuleDispatcherInfo() {
    $.ajax({
        type: 'POST',
        url: '/ajax/module/test/get',
        data: {
            module_id: $input_module_id.val(),
        },
        success: function (data, status, xhr) {
            if (data.error_no === 0){
                if (data.status === '正在运行') {
                    dispatcher_id = data.dispatcher_id;
                    moduleDispatcherRunning();
                }else if (data.status === '正在停止'){
                    moduleDispatcherStopping();
                }else if (data.status === '已停止' || data.status === '已完成'){
                    moduleDispatcherStoppedFinished();
                }
            }else{
                message("模块测试数据查询失败: " + data.error_msg, "info");
                moduleDispatcherStoppedFinished();
            }
        },
    });
}

// 模块调度不同状态-正在启动 运行中 已停止/已完成 正在停止 缺省状态
function moduleDispatcherStarting() {
    $btn_start_module_test.text('正在启动');
    $btn_start_module_test.attr('disabled', true);
    $btn_start_module_test.append("<span class=\"spinner-grow spinner-grow-sm\"></span>")
    $btn_stop_module_test.removeAttr('disabled');
}
function moduleDispatcherRunning() {
    $btn_start_module_test.text('正在执行');
    $btn_start_module_test.attr('disabled', true);
    $btn_start_module_test.append("<span class=\"spinner-grow spinner-grow-sm\"></span>")
    $btn_stop_module_test.removeAttr('disabled');
}
function moduleDispatcherStoppedFinished() {
    $btn_start_module_test.text('执行测试');
    $btn_stop_module_test.text('终止测试');
    $btn_start_module_test.removeAttr('disabled');
    $btn_stop_module_test.attr('disabled', true);
}
function moduleDispatcherStopping() {
    $btn_start_module_test.text('执行测试');
    $btn_start_module_test.attr('disabled', true);
    $btn_stop_module_test.text('正在终止');
    $btn_stop_module_test.append("<span class=\"spinner-grow spinner-grow-sm\"></span>")
}

// 支持页面左右分割
function renderSplitter() {
    Split(['#scene-navigation', '#div-container-element'], {
        // https://github.com/nathancahill/split/tree/master/packages/splitjs
        sizes: [20, 80],
        minSize: [50, 500],
        expandToMin: true,
        gutterSize: 10,
        direction: 'horizontal',
        cursor: 'col-resize',
        gutter: function (index, direction, pairElement) {
            const gutter = document.createElement('div');
            gutter.className = `gutter gutter-${direction} div-split-gutter-vertical`;
            return gutter
        }
        // direction: 'vertical',
    });
}

function traverseAllSceneElementAndLoadDom() {
    // 获取左侧导航节点中所有场景组件
    let $element_scenes = $('.item-scene');
    let scene_id = 0;
    let promise_array = [];
    $.each($element_scenes, function (index, element_scene) {
        scene_id = $(element_scene).data('scene-id');
        promise_array.push(addSceneElement(scene_id));
    });
    return promise_array;
}
function traverseSpecifiedSceneElementAndLoadDom($element_scenes) {
    // 遍历指定的Dom中的场景组件
    let scene_id = 0;
    $.each($element_scenes, function (index, element_scene) {
        scene_id = $(element_scene).data('scene-id');
        addSceneElement(scene_id);
    })
}
function traverseAllLogicControllerElementAndLoadDom() {
    // 获取左侧导航节点中所有逻辑组件
    let $element_logic_controllers = $('.logic-controller');
    let logic_controller_id = 0;
    let promise_array = [];
    $.each($element_logic_controllers, function (index, element_logic_controller) {
        logic_controller_id = $(element_logic_controller).data('logic-controller-id');
        promise_array.push(addLogicControllerElement(logic_controller_id));
    });
    return promise_array;
}
function traverseSpecifiedLogicControllerElementAndLoadDom($element_logic_controllers) {
    // 遍历指定的Dom中的逻辑控制器组件
    let logic_controller_id = 0;
    $.each($element_logic_controllers, function (index, element_logic_controller) {
        logic_controller_id = $(element_logic_controller).data('logic-controller-id');
        addLogicControllerElement(logic_controller_id)
    })
}
function traverseAllCaseElementAndLoadDom() {
    // 获取左侧导航节点中所有案例组件
    let $element_cases = $('.item-case');  // TODO element_cases 改为 item_cases
    let case_id = 0;
    let promise_array = [];
    $.each($element_cases, function (index, element_case) {
        case_id = $(element_case).data('case-id');
        promise_array.push(addCaseElement(case_id));
    });
    return promise_array;
}
function traverseSpecifiedCaseElementAndLoadDom($element_cases) {  // TODO element_cases改为item_cases
    // 遍历指定的Dom中的案例组件
    let case_id = 0;
    $.each($element_cases, function (index, element_case) {
        case_id = $(element_case).data('case-id');
        addCaseElement(case_id);
    })
}
function traverseAllToolElementAndLoadDom() {
     // 获取左侧导航节点中所有案例组件
    let $item_tools = $('.item-tool');
    let tool_id = 0;
    let promise_array = [];
    $.each($item_tools, function (index, item_tool) {
        tool_id = $(item_tool).data('tool-id');
        promise_array.push(addToolElement(tool_id));
    });
    return promise_array;
}
function traverseSpecifiedToolElementAndLoadDom($item_tools) {
    // 遍历指定的Dom中的工具组件
    let tool_id = 0;
    $.each($item_tools, function (index, item_tool) {
        tool_id = $(item_tool).data('tool-id');
        addToolElement(tool_id);
    })
}

// 遍历所有组件并初始化Dom
function traverseAllElementAndLoadDom() {
    let promise_array = [];
    // 遍历所有场景并初始化Dom
    promise_array.push(traverseAllSceneElementAndLoadDom());
    // 遍历所有逻辑控制器并初始化Dom
    promise_array.push(traverseAllLogicControllerElementAndLoadDom());
    // 遍历所有案例并初始化Dom
    promise_array.push(traverseAllCaseElementAndLoadDom());
    // 遍历所有工具并初始化Dom
    promise_array.push(traverseAllToolElementAndLoadDom());
    let new_promise_array = [];
    // 将promise_array铺平
    $.each(promise_array, function (index, array) {
        $.each(array, function (idenx, promise) {
            new_promise_array.push(promise);
        });
    });
    Promise.all(new_promise_array).then((result) => {
        // console.log('then');
        // console.log(result);               // [['成功了', 'success'], ...]
        $div_element_data_load_spinner.css("cssText", "display: none !important;");
        // 如果当前已经有组件展示则不再展示空页面
        let element_data_show = false;
        $.each($('.element-data'), function (index, elementData) {
            if(!$(elementData).is(":hidden")){
                element_data_show = true;
                return false;
            }
        });
        if(!element_data_show){
            $div_element_blank.css('display', '');
        }
    }).catch((error) => {
        // console.log('catch');
        // console.log(error);
    }).finally(() => {
        // console.log('finally');
    });
}

// 保存组件数据
function documentSaveElement(event) {
    //可以判断是不是mac，如果是mac,ctrl变为花键
    if (event.keyCode == 83 && (navigator.platform.match("Mac") ? event.metaKey : event.ctrlKey)) {
        event.preventDefault();  // 阻止元素事件的默认行为
        // 获取当前正在展示的组件
        let $allElements = $('.element-data');
        let element_type = '';
        let element_id = '';
        $.each($allElements, function (index, element) {
            if(!$(element).is(":hidden")){  // 找到没有隐藏的组件
                if($(element).hasClass('element-scene')){  // 当前展示场景组件
                    // element_type = 'SCENE';
                    element_id = $(element).data('scene-id');
                    // 找到保存按钮，触发click
                    $(element).find(`#btn-scene-setting-save-${element_id}`).click();
                    // let sceneElement = getSceneElement(element_id);
                    // sceneElement.saveSceneSetting();
                }else if($(element).hasClass('element-logic-controller')){  // 当前展示逻辑控制器组件
                    let logic_controller_id = $(element).data('logic-controller-id');
                    $(element).find(`#btn-logic-controller-save-${logic_controller_id}`).click();
                }else if($(element).hasClass('element-case')) {  // 当前展示案例组件
                    let case_id = $(element).data('case-id');
                    $(element).find(`#btn-case-save-${case_id}`).click();
                }else if($(element).hasClass('element-tool')) {  // 当前展示案例组件
                    let tool_id = $(element).data('tool-id');
                    $(element).find(`#btn-tool-save-${tool_id}`).click();
                }
                return false;  // 退出$.each循环
            }
        });
    }
}

// 在页面上加载场景数据组件
function addSceneElement(scene_id) {
    // 异步请求获取对应场景id的dom组件
    let promise = new Promise((resolve, reject) => {
        $.ajax({
            type: 'POST',
            url: '/ajax/scene',
            data: {
                scene_id: scene_id,
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    $div_container_element.append(data.html_text);
                    let element = getSceneElement(scene_id);
                    element.init();
                    resolve(['成功了', 'success']);  // 也可以传递其他类型参数
                }else{
                    message("场景组件加载失败: " + data.error_msg, "error");
                }
            },
        });
    });
    return promise;
}
// 在页面上加载逻辑控制器组件
function addLogicControllerElement(logic_controller_id) {
    // 异步请求获取对应逻辑控制器id的dom组件
    let promise = new Promise((resolve, reject) => {
        $.ajax({
            type: 'POST',
            url: '/ajax/logic_controller',
            data: {
                logic_controller_id: logic_controller_id,
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    $div_container_element.append(data.html_text);
                    if(data.logic_controller_type === 'IF') {
                        let element = getIfControllerElement(data.logic_controller_id);
                        element.init();
                        element_logic_controller_dict[data.logic_controller_id] = element;
                    }else if(data.logic_controller_type === 'SIMPLE'){
                        let element = getSimpleControllerElement(data.logic_controller_id);
                        element.init();
                        element_logic_controller_dict[data.logic_controller_id] = element;
                    }else if(data.logic_controller_type === 'LOOP'){
                        let element = getLoopControllerElement(data.logic_controller_id);
                        element.init();
                        element_logic_controller_dict[data.logic_controller_id] = element;
                    }else if(data.logic_controller_type === 'WHILE'){
                        let element = getWhileControllerElement(data.logic_controller_id);
                        element.init();
                        element_logic_controller_dict[data.logic_controller_id] = element;
                    }
                    resolve(['成功了', 'success']);  // 也可以传递其他类型参数
                }else{
                    message("逻辑组件加载失败: " + data.error_msg, "error");
                }
            },
        });
    });
    return promise;
}
// 在页面上加载案例组件
function addCaseElement(case_id, case_type) {
    // 异步请求获取对应案例id的dom组件
    let promise = new Promise((resolve, reject) => {
        $.ajax({
            type: 'POST',
            url: '/ajax/case',
            data: {
                case_id: case_id,
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    $div_container_element.append(data.html_text);
                        if(data.case_type === 'SSH') {
                        let element = getSSHCaseElement(case_id, data.case_type);  // TODO case_id 改为 data.case_id
                        element.init(data.data_expectations);
                        element_case_instance_dict[case_id] = element;
                        element_case_first_show_flag[case_id] = false;
                    }else if(data.case_type === 'SQL'){
                        let element = getSQLCaseElement(case_id, data.case_type);
                        element.init(data.data_expectations);
                        element_case_instance_dict[case_id] = element;
                        element_case_first_show_flag[case_id] = false;
                    }else if(data.case_type === 'HTTP'){
                        let element = getHTTPCaseElement(case_id, data.case_type);
                        element.init(data.data_expectations, data.data_parameters, data.data_headers, data.data_file_upload);
                        element_case_instance_dict[case_id] = element;
                        element_case_first_show_flag[case_id] = false;
                    }
                    else if(data.case_type === 'DEBUG'){
                        let element = getDebugCaseElement(case_id, data.case_type);
                        element.init(data.data_expectations);
                        element_case_instance_dict[case_id] = element;
                        element_case_first_show_flag[case_id] = false;
                    }
                    resolve(['成功了', 'success']);  // 也可以传递其他类型参数
                }else{
                    message("案例组件加载失败: " + data.error_msg, "error");
                }
            },
        });
    });
    return promise;
}
// 在页面上加载工具组件
function addToolElement(tool_id) {
    // 异步请求获取对应工具id的dom组件
    let promise = new Promise((resolve, reject) => {
        $.ajax({
            type: 'POST',
            url: '/ajax/tool',
            data: {
                tool_id: tool_id,
            },
            success: function (data, status, xhr) {
                if (data.error_no === 0){
                    $div_container_element.append(data.html_text);
                    if(data.tool_type === 'TIMER') {
                        let element = getTimerToolElement(data.tool_id);
                        element.init();
                        element_tool_dict[data.tool_id] = element;
                    }else if(data.tool_type === 'SCRIPT') {
                        let element = getScriptToolElement(data.tool_id);
                        element.init();
                        element_tool_dict[data.tool_id] = element;
                    }else if(data.tool_type === 'VARIABLE_DEFINITION') {
                        let element = getVariableDefinitionToolElement(data.tool_id);
                        element.init(data.data_variables);
                        element_tool_dict[data.tool_id] = element;
                    }else if(data.tool_type === 'HTTP_HEADER_MANAGER') {
                        let element = getHTTPHeaderManagerToolElement(data.tool_id);
                        element.init(data.data_variables);
                        element_tool_dict[data.tool_id] = element;
                    }else if(data.tool_type === 'HTTP_COOKIE_MANAGER') {
                        let element = getHTTPCookieManagerToolElement(data.tool_id);
                        element.init(data.data_attributes);
                        element_tool_dict[data.tool_id] = element;
                    }
                    resolve(['成功了', 'success']);  // 也可以传递其他类型参数
                }else{
                    message("工具组件加载失败: " + data.error_msg, "error");
                }
            },
        });
    });
    return promise;
}

// 点击左侧导航栏组件时样式重置
function navigationElementRemoveActiveClass() {
    let $itemSceneHeaders = $('.item-scene-header');
    $itemSceneHeaders.removeClass('active');
    let $logicControllerHeaders = $('.specific-logic-controller');
    $logicControllerHeaders.removeClass('active');
    let $divItemCases = $('.item-case');
    $divItemCases.removeClass('active');
    let $divItemTools = $('.item-tool');
    $divItemTools.removeClass('active');
}
